/**
 * 
 */
package beans.soap;

import java.util.HashMap;
import java.util.Iterator;

import javax.servlet.annotation.WebServlet;
import javax.xml.messaging.JAXMServlet;
import javax.xml.messaging.ReqRespListener;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.w3c.dom.NodeList;

/**
 * 
 * 有些对象是虚拟的，目前只保证不报错
 * 
 * @author Beanstao@gmail.com
 * @date 2013-10-9
 * @version 1.0
 */
@WebServlet(name = "SOAPServlet", urlPatterns = "/SOAPServlet")
public class SOAPServlet extends JAXMServlet implements ReqRespListener
{

	private static final long serialVersionUID = 1L;

	@Override
	public SOAPMessage onMessage(SOAPMessage arg0)
	{
		// 处理并响应协议类
		// XXResponse response = new XXResponse();
		try
		{
			// 得到SOAP对象的信封Envelope
			@SuppressWarnings("unused")
			SOAPEnvelope envelope = arg0.getSOAPPart().getEnvelope();
			// handleSoapRequest(response, envelope);
		}
		catch (SOAPException e)
		{
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unused")
	private void handleSoapRequest(QueueTradeResponse qr, SOAPEnvelope envelope) throws SOAPException
	{
		HashMap<String, String> requestHeaderDict = getHeaderDict(envelope);
		if ((!requestHeaderDict.containsKey("TradeCode")) || ("".equals(requestHeaderDict.get("TradeCode"))))
		{
			qr.setHeaderValue("RetCode", "-1");
			qr.setHeaderValue("RetMessage", "请求报文缺少报文码");
			return;
		}
		String tradeCode = requestHeaderDict.get("TradeCode");

		HashMap<String, String> requestBodyDict = getBodyDict(envelope);

		IQueueResponseHandler handler = getHandlerByTradeCode(tradeCode);
		if (handler == null)
		{
			qr.setHeaderValue("RetCode", "-2");
			qr.setHeaderValue("RetMessage", "报文码" + tradeCode + "未知");
			return;
		}

		handler.setResponse(qr, requestBodyDict);
	}

	private IQueueResponseHandler getHandlerByTradeCode(String tradeCode)
	{
		// TODO Auto-generated method stub
		return null;
	}

	public SOAPMessage generateResponseMessage(QueueTradeResponse qr)
	{
		try
		{
			SOAPMessage message = msgFactory.createMessage();
			message.setProperty("javax.xml.soap.character-set-encoding", "utf-8");

			SOAPPart soapPart = message.getSOAPPart();
			SOAPEnvelope envelope = soapPart.getEnvelope();

			envelope.addNamespaceDeclaration("bip", "http://bip.bankit.com.cn/bip");

			SOAPHeader header = envelope.getHeader();
			for (String headerKey : qr.getHeaderKeySet())
			{
				header.addChildElement(headerKey, "bip").addTextNode(qr.getHeaderValue(headerKey));
			}

			SOAPBody body = envelope.getBody();
			SOAPElement bodyElement = body.addChildElement("Reponse", "bip");
			for (String bodyKey : qr.getBodyKeySet())
			{
				bodyElement.addChildElement(bodyKey).addTextNode(qr.getBodyValue(bodyKey));
			}

			message.saveChanges();
			return message;
		}
		catch (SOAPException ex)
		{
			ex.printStackTrace();
		}
		return null;
	}

	private HashMap<String, String> getHeaderDict(SOAPEnvelope envelope) throws SOAPException
	{
		HashMap<String, String> map = new HashMap<String, String>();

		SOAPHeader header = envelope.getHeader();

		@SuppressWarnings("rawtypes")
		Iterator it = header.getChildElements();

		while (it.hasNext())
		{
			SOAPHeaderElement ele = (SOAPHeaderElement) it.next();
			map.put(ele.getLocalName(), ele.getValue());
		}

		return map;
	}

	private HashMap<String, String> getBodyDict(SOAPEnvelope envelope) throws SOAPException
	{
		HashMap<String, String> map = new HashMap<String, String>();
		SOAPBody body = envelope.getBody();

		Node node = (Node) body.getFirstChild();
		NodeList nodeList = node.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++)
		{
			map.put(nodeList.item(i).getLocalName(), nodeList.item(i).getTextContent());
		}

		return map;
	}
}
